package ec.linde.modulos.proyectos;

import java.io.File;
import java.io.FileInputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.data.gantt.Task;
import org.jfree.data.gantt.TaskSeries;
import org.jfree.data.gantt.TaskSeriesCollection;
import org.jfree.data.time.SimpleTimePeriod;
import org.primefaces.component.datatable.DataTable;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;
import org.primefaces.model.StreamedContent;

import ec.linde.enumeraciones.Estado;
import ec.linde.modulos.proyectos.servicio.ServicioDatosBaseProyectos;
import ec.linde.modulos.proyectos.servicio.ServicioFeriado;
import ec.linde.modulos.proyectos.servicio.ServicioPlanOperativo;
import ec.linde.modulos.proyectos.servicio.ServicioProyecto;
import ec.linde.modulos.proyectos.servicio.ServicioRdo;
import ec.linde.modulos.recursos.FuncionesUtiles;
import ec.linde.persistencia.entidades.ProdConceptos;
import ec.linde.persistencia.entidades.ProdPartidaDetalle;
import ec.linde.persistencia.entidades.ProdPartidasConceptos;
import ec.linde.persistencia.entidades.proyectos.CronogramaPlanOperativo;
import ec.linde.persistencia.entidades.proyectos.CronogramaRdo;
import ec.linde.persistencia.entidades.proyectos.DetallePlanOperativo;
import ec.linde.persistencia.entidades.proyectos.DetalleRdo;
import ec.linde.persistencia.entidades.proyectos.Feriado;
import ec.linde.persistencia.entidades.proyectos.PlanOperativo;
import ec.linde.persistencia.entidades.proyectos.Proyecto;
import ec.linde.persistencia.entidades.proyectos.Rdo;

/**
 * TODO: Agregar descripcion
 * 
 * @FechaCreacion: 29/03/2013
 * @author: Alex Carrillo
 * @FechaModificacion: 29/03/2013
 * @author: Alex Carrillo
 * @version: 1.0
 */
@ManagedBean
@ViewScoped
public class PlanOperativoBean extends PageController {

	private static final long serialVersionUID = 1L;

	/**
	 * Servicios
	 */
	@EJB
	private ServicioPlanOperativo servicioPlanOperativo;
	@EJB
	private ServicioProyecto servicioProyecto;
	@EJB
	private ServicioDatosBaseProyectos servicioDatosBaseProyectos;
	@EJB
	private ServicioFeriado servicioFeriado;
	@EJB
	private ServicioRdo servicioRdo;

	/**
	 * Atributos Forma
	 */
	private PlanOperativo planOperativo;
	private DetallePlanOperativo detallePlanOperativoSeleccionado;
	private Integer idProyecto;
	private HashMap<Date, Feriado> hmFeriado;
	private StreamedContent chartImage;
	private ProdPartidaDetalle partida;

	/**
	 * Listados 1. Lista Lazy DataModel 2. Lista Detalles 3. Listas Combo
	 */
	private LazyDataModel<PlanOperativo> listaPlanOperativo;
	private List<ProdConceptos> listaConceptos;
	private List<ProdPartidaDetalle> listaPartidas;
	private List<DetallePlanOperativo> listaDetallePlanOperativo;

	/**
	 * UI
	 */
	private DataTable dtPlanOperativo;
	private DataTable dtDetallePlanOperativo;
	private DataTable dtCronogramaPlanOperativo;

	/**
	 * PostContrutor
	 */
	@PostConstruct
	public void init() {

		listaPlanOperativo = new LazyDataModel<PlanOperativo>() {

			private static final long serialVersionUID = 1L;

			@Override
			public List<PlanOperativo> load(int startIndex, int pageSize, String sortField, SortOrder sortOrder, Map<String, String> filters) {
				List<PlanOperativo> lista = new ArrayList<PlanOperativo>();

				boolean ordenar = sortOrder == SortOrder.ASCENDING ? true : false;
				lista = servicioPlanOperativo.obtenerListaPorPagina(startIndex, pageSize, sortField, ordenar, filters);

				listaPlanOperativo.setRowCount(servicioPlanOperativo.contarPorCriterio(filters));

				return lista;
			}
		};

	}

	/**
	 * Metodos
	 */

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.asinfo.as2.controller.PageControllerAS2#editar()
	 */
	public String editar() {
		if (getPlanOperativo() != null) {
			if (planOperativo.getEstado() == Estado.ELABORADO) {
				planOperativo = servicioPlanOperativo.cargarDetalle(getPlanOperativo().getId());
				setEditado(true);
			} else {
				addInfoMessage("Accion no permitida");
			}

		} else {
			addInfoMessage("Seleccione un Registro");
		}
		return "";
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.asinfo.as2.controller.PageControllerAS2#guardar()
	 */
	public String guardar() {

		String resultado = "";

		try {
			if (validar()) {
				calcularFechasPlanOperativo();
				actualizarCronograma();
				servicioPlanOperativo.guardar(planOperativo);
				addInfoMessage("Registro Guardado Correctamente");
				setEditado(false);
				limpiar();
				resultado = "planOperativo.xhtml?faces-redirect=true";
			} else {
				resultado = "";
			}

		} catch (Exception e) {
			addErrorMessage("Error al Guardar el registro");
		}

		return resultado;

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.asinfo.as2.controller.PageControllerAS2#eliminar()
	 */
	public String eliminar() {
		try {
			servicioPlanOperativo.eliminar(planOperativo);
			limpiar();
			addInfoMessage("Registro Eliminado con Correctamente");
		} catch (Exception e) {
			addErrorMessage("Error al Eliminar el registro");
		}
		return "";
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.asinfo.as2.controller.PageControllerAS2#limpiar()
	 */
	@Override
	public String limpiar() {
		planOperativo = null;
		return "";
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ec.linde.modulos.proyectos.PageController#cancelar()
	 */
	@Override
	public String cancelar() {
		setEditado(false);
		limpiar();
		return "planOperativo.xhtml?faces-redirect=true";
	}

	/**
	 * TODO: Agregar descripcion del metodo
	 * 
	 * @return
	 */
	public List<DetallePlanOperativo> getListaDetallePlanOperativo() {

		if (listaDetallePlanOperativo == null) {
			listaDetallePlanOperativo = new ArrayList<DetallePlanOperativo>();
			for (DetallePlanOperativo detallePlanOperativo : planOperativo.getListaDetallePlanOperativo()) {
				if (!detallePlanOperativo.isEliminado()) {
					listaDetallePlanOperativo.add(detallePlanOperativo);
				}
			}
		}

		return listaDetallePlanOperativo;
	}

	/**
	 * TODO: Agregar descripcion del metodo
	 */
	public void agregarDetallePlanOperativo() {
		DetallePlanOperativo detallePlanOperativo = new DetallePlanOperativo();
		detallePlanOperativo.setPlanOperativo(planOperativo);
		planOperativo.getListaDetallePlanOperativo().add(detallePlanOperativo);
		listaDetallePlanOperativo = null;
	}

	/**
	 * TODO: Agregar descripcion del metodo
	 * 
	 * @param contacto
	 */
	public void eliminarDetallePlanOperativo(DetallePlanOperativo detallePlanOperativo) {
		detallePlanOperativo.setEliminado(true);
		listaDetallePlanOperativo = null;
		totalizar();
	}

	/**
	 * TODO: Agregar descripcion del metodo
	 * 
	 * @return
	 */
	public List<CronogramaPlanOperativo> getListaCronogramaPlanOperativo() {
		List<CronogramaPlanOperativo> lista = new ArrayList<CronogramaPlanOperativo>();
		if (detallePlanOperativoSeleccionado != null) {
			for (CronogramaPlanOperativo cronogramaPlanOperativo : detallePlanOperativoSeleccionado.getListaCronogramaPlanOperativo()) {
				if (!cronogramaPlanOperativo.isEliminado()) {
					lista.add(cronogramaPlanOperativo);
				}
			}
		}
		FuncionesUtiles.ordenaLista(lista, "fecha", true);
		return lista;
	}

	/**
	 * Carga el plan operativo ya sea desde el proyecto o desde el ultimo plan operativo
	 */
	public void cargarPlanOperativoDesdeProyecto() {

		if (idProyecto != null && this.planOperativo == null) {

			PlanOperativo po = servicioPlanOperativo.obtenerPlanOperativoActivo(idProyecto);

			if (po == null) {

				Proyecto proyecto = servicioProyecto.cargarDetalle(idProyecto);
				this.planOperativo = new PlanOperativo();
				this.planOperativo.setProyecto(proyecto);
				this.planOperativo.setVersion(1);
				this.planOperativo.setEstado(Estado.ELABORADO);
				this.planOperativo.setFecha(new Date());
				for (ProdPartidaDetalle prodPartidaDetalle : proyecto.getProforma().getProdPartidaDetalles()) {
					for (ProdPartidasConceptos prodPartidasConceptos : prodPartidaDetalle.getProdPartidasConceptoses()) {

						DetallePlanOperativo detallePlanOperativo = new DetallePlanOperativo();
						detallePlanOperativo.setPartida(prodPartidasConceptos.getProdPartidaDetalle());
						detallePlanOperativo.setConcepto(prodPartidasConceptos.getProdConceptos());

						detallePlanOperativo.setCantidad(FuncionesUtiles.redondearBigDecimal(new BigDecimal(prodPartidasConceptos.getPacoCantidad()),
								2));
						BigDecimal sumaCostos = new BigDecimal(prodPartidasConceptos.getPacoCostoDirectoUnitario()
								+ prodPartidasConceptos.getPacoCostoIndirectoUnitario());
						detallePlanOperativo.setCostoUnitario(FuncionesUtiles.redondearBigDecimal(
								sumaCostos.multiply(detallePlanOperativo.getCantidad()), 2));

						detallePlanOperativo.setPlanOperativo(this.planOperativo);
						this.planOperativo.getListaDetallePlanOperativo().add(detallePlanOperativo);
					}
				}

				totalizar();
				setEditado(true);

			} else {
				if (po.getEstado() == Estado.ELABORADO) {

					this.planOperativo = servicioPlanOperativo.cargarDetalle(po.getIdPlanOperativo());
					setEditado(true);

				} else if (po.getEstado() == Estado.APROBADO) {

					PlanOperativo planOperativo = servicioPlanOperativo.cargarDetalle(po.getIdPlanOperativo());
					this.planOperativo = servicioPlanOperativo.copiarPlanOperativo(planOperativo);
					setEditado(true);

				} else {
					System.out.println("Entro a estado laborado..");
				}

			}

			actualizarCronograma();

		}
	}

	/**
	 * Selecciona la fila del Detalle operativo
	 * 
	 * @param event
	 */
	public void seleccionarDetallePlanOperativo(SelectEvent event) {
		detallePlanOperativoSeleccionado = (DetallePlanOperativo) event.getObject();
	}

	/**
	 * Selecciona la fila del Detalle operativo
	 */
	public void seleccionarDtDetallePlanOperativo() {
		detallePlanOperativoSeleccionado = (DetallePlanOperativo) dtDetallePlanOperativo.getRowData();
		generarCronogramaPlanOperativo(detallePlanOperativoSeleccionado);
		totalizar();
	}

	/**
	 * Genera el plan operativo
	 * 
	 * @param detallePlanOperativo
	 */
	public void generarCronogramaPlanOperativo(DetallePlanOperativo detallePlanOperativo) {

		for (CronogramaPlanOperativo cronogramaPlanOperativo : detallePlanOperativo.getListaCronogramaPlanOperativo()) {
			cronogramaPlanOperativo.setEliminado(true);
		}

		int diasTarea = detallePlanOperativo.getDiasTarea() - 1;

		if (diasTarea >= 0) {

			// Declaro e instancio las variables de las fechas de inicio y fin
			Calendar fechaInicial = Calendar.getInstance();
			fechaInicial.setTime(FuncionesUtiles.setAtributoFecha(detallePlanOperativo.getFechaInicio()));
			Calendar fechaFinal = Calendar.getInstance();

			fechaFinal.setTime(FuncionesUtiles.sumarFechaDiasMeses(fechaInicial.getTime(), diasTarea));
			// mientras la fecha inicial sea menor o igual que la fecha final se cuentan los dias
			while (fechaInicial.before(fechaFinal) || fechaInicial.equals(fechaFinal)) {

				// si el dia de la semana de la fecha minima es diferente de sabado o domingo
				if (fechaInicial.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY && fechaInicial.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY) {
					// se aumentan los dias de diferencia entre min y max
					SimpleDateFormat f = new SimpleDateFormat("EEEE", new Locale("ES"));
					String nombreDia = f.format(fechaInicial.getTime());

					CronogramaPlanOperativo cronogramaPlanOperativo = new CronogramaPlanOperativo();
					cronogramaPlanOperativo.setFecha(fechaInicial.getTime());
					cronogramaPlanOperativo.setDetallePlanOperativo(detallePlanOperativo);
					cronogramaPlanOperativo.setNombreDia(nombreDia);
					if (getHmFeriado().containsKey(fechaInicial.getTime())) {
						cronogramaPlanOperativo.setDiaNoLaborable(true);
					}
					detallePlanOperativo.getListaCronogramaPlanOperativo().add(cronogramaPlanOperativo);

				} else {

					SimpleDateFormat f = new SimpleDateFormat("EEEE", new Locale("ES"));
					String nombreDia = f.format(fechaInicial.getTime());

					CronogramaPlanOperativo cronogramaPlanOperativo = new CronogramaPlanOperativo();
					cronogramaPlanOperativo.setFecha(fechaInicial.getTime());
					cronogramaPlanOperativo.setDetallePlanOperativo(detallePlanOperativo);
					cronogramaPlanOperativo.setNombreDia(nombreDia);
					cronogramaPlanOperativo.setDiaNoLaborable(true);
					detallePlanOperativo.getListaCronogramaPlanOperativo().add(cronogramaPlanOperativo);
					fechaFinal.add(Calendar.DATE, 1);

				}
				// se suma 1 dia para hacer la validacion del siguiente dia.
				fechaInicial.add(Calendar.DATE, 1);
			}
			detallePlanOperativo.setFechaFin(fechaFinal.getTime());
		}

		// // mientras la fecha inicial sea menor o igual que la fecha final se cuentan los dias
		// // while (fechaInicial.before(fechaFinal) || fechaInicial.equals(fechaFinal)) {
		// while (fechaInicial.before(fechaFinal)) {
		//
		// // si el dia de la semana de la fecha minima es diferente de sabado o domingo
		// if (fechaInicial.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY && fechaInicial.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY) {
		// // se aumentan los dias de diferencia entre min y max
		// SimpleDateFormat f = new SimpleDateFormat("EEEE", new Locale("ES"));
		// String nombreDia = f.format(fechaInicial.getTime());
		//
		// CronogramaPlanOperativo cronogramaPlanOperativo = new CronogramaPlanOperativo();
		// cronogramaPlanOperativo.setFecha(fechaInicial.getTime());
		// cronogramaPlanOperativo.setDetallePlanOperativo(detallePlanOperativo);
		// cronogramaPlanOperativo.setNombreDia(nombreDia);
		// detallePlanOperativo.getListaCronogramaPlanOperativo().add(cronogramaPlanOperativo);
		//
		// } else {
		// fechaFinal.add(Calendar.DATE, 1);
		// }
		// // se suma 1 dia para hacer la validacion del siguiente dia.
		// fechaInicial.add(Calendar.DATE, 1);
		// }
		//

	}

	/**
	 * Calcula la fecha de inicio y la fecha fin del plan operativo
	 */
	public void calcularFechasPlanOperativo() {

		TreeMap<Date, Date> tmFecha = new TreeMap<Date, Date>();

		for (DetallePlanOperativo detallePlanOperativo : planOperativo.getListaDetallePlanOperativo()) {
			if (!detallePlanOperativo.isEliminado()) {
				for (CronogramaPlanOperativo cronogramaPlanOperativo : detallePlanOperativo.getListaCronogramaPlanOperativo()) {
					if (!cronogramaPlanOperativo.isEliminado() && !tmFecha.containsKey(cronogramaPlanOperativo.getFecha())) {
						tmFecha.put(cronogramaPlanOperativo.getFecha(), cronogramaPlanOperativo.getFecha());
					}
				}
			}
		}

		if (!tmFecha.isEmpty()) {
			Date fechaInicio = FuncionesUtiles.obtenerMinimaFechaLista(new ArrayList<Date>(tmFecha.values()));
			Date fechaFin = FuncionesUtiles.obtenerMaximaFechaLista(new ArrayList<Date>(tmFecha.values()));
			planOperativo.setFechaInicio(fechaInicio);
			planOperativo.setFechaFin(fechaFin);
		}

	}

	/**
	 * Aprueba el plan operativo
	 */
	public void aprobar() {
		if (planOperativo != null) {
			if (planOperativo.getEstado() == Estado.ELABORADO) {
				
				if (validarAprobacion(planOperativo)) {
					servicioPlanOperativo.cambiarEstado(getPlanOperativo().getId(), Estado.APROBADO);
					servicioPlanOperativo.cambiarEstadoPlanOperativoAnteriores(planOperativo, Estado.REEMPLAZADO);
					addInfoMessage("El registro se ha aprobado correctamente");
				}
				
			} else {
				addInfoMessage("Solo los planos operativos elaborados pueden ser aprobados");
			}

		} else {
			addInfoMessage("Seleccione un Registro");
		}

	}

	private boolean validarAprobacion(PlanOperativo planOperativo) {
		
		boolean resultado=true;

		HashMap<String, String> filters = new HashMap<String, String>();
		filters.put("planOperativo.proyecto.numero", "" + planOperativo.getProyecto().getNumero());
		filters.put("planOperativo.estado", "" + Estado.APROBADO);
		List<Rdo> lista = servicioRdo.obtenerListaCombo("", true, filters);

		if (!lista.isEmpty()) {

			// Cargo el detalle del Rdo
			Rdo rdo = servicioRdo.cargarDetalle(lista.get(0).getIdRdo());

			// Creo hasmap del detalle del plan operativo y llleno el hasmap
			HashMap<String, DetallePlanOperativo> hmDetallePlanOperativo = new HashMap<String, DetallePlanOperativo>();
			for (DetallePlanOperativo dpo : planOperativo.getListaDetallePlanOperativo()) {
				if (!dpo.isEliminado()) {
					hmDetallePlanOperativo.put(dpo.getPartida().getPadeId() + "~" + dpo.getConcepto().getConcId(), dpo);
				}
			}

			
			// Comparo los detalles entre el plan operativo y el rdo
			outer:
			for (DetalleRdo drdo : rdo.getListaDetalleRdo()) {

				DetallePlanOperativo detallePlanOperativo = hmDetallePlanOperativo.get(drdo.getPartida().getPadeId() + "~"
						+ drdo.getConcepto().getConcId());

				if (detallePlanOperativo != null) {
					
					Date fechaInicioPO=FuncionesUtiles.setAtributoFecha(detallePlanOperativo.getFechaInicio());
					Date fechaFinPO=FuncionesUtiles.setAtributoFecha(detallePlanOperativo.getFechaFin());
					Date fechaInicioRDO=FuncionesUtiles.setAtributoFecha(drdo.getFechaInicio());
					Date fechaFinRDO=FuncionesUtiles.setAtributoFecha(drdo.getFechaFin());
					
					//Verifico los avances entre las fechas de inicio del po y el rdo cuando la fecha de inicio del po es mayor a la fecha de inicio del rdo  
					if  (fechaInicioPO.compareTo(fechaInicioRDO) == 1) {
						
						while (fechaInicioRDO.compareTo(fechaInicioPO) == -1 || fechaInicioRDO.compareTo(fechaInicioPO) == 0 ) {
							CronogramaRdo cronogramaRdo = drdo.getTmCronogramaRdoConDiasLaborables().get(fechaInicioRDO);
							if (cronogramaRdo.getAvance().compareTo(BigDecimal.ZERO)!=0) {
								//Poner mensaje que no vale aprobar ya que existe un avance para la fecha
								addErrorMessage(" Existen avances ya registrados en el RDO para la Actividad: " + drdo.getPartida().getPadeNombre() +" Tarea: " +drdo.getConcepto().getConcNombre());
								resultado = false;
								break outer;
							}
							FuncionesUtiles.sumarFechaDiasMeses(fechaInicioRDO, 1);
						}
					}
					
					//Verifico los avances entre las fechas de fin del po y el rdo cuando la fecha de fin del po es menor a la fecha de menor del rdo
					if (fechaFinPO.compareTo(fechaFinRDO) == -1) {
						while (fechaFinPO.compareTo(fechaFinRDO) == -1 || fechaFinPO.compareTo(fechaFinRDO) == 0 ) {
							
							CronogramaRdo cronogramaRdo = drdo.getTmCronogramaRdoConDiasLaborables().get(fechaFinPO);
							if (cronogramaRdo.getAvance().compareTo(BigDecimal.ZERO)!=0) {
								//Poner mensaje que no vale aprobar ya que existe un avance para la fecha
								addErrorMessage(" Existen avances ya registrados en el RDO para la Actividad: " + drdo.getPartida().getPadeNombre() +" Tarea: " +drdo.getConcepto().getConcNombre());
								resultado = false;
								break outer;
							}
							FuncionesUtiles.sumarFechaDiasMeses(fechaFinPO, 1);
						}
					}
				}

			}
		}
		return resultado;
	}

	/**
	 * Totaliza los valores del plan operativo
	 */
	public void totalizar() {

		// Totaliza el costo de la tarea y prorratea la catidad al cronograma
		for (DetallePlanOperativo detallePlanOperativo : planOperativo.getListaDetallePlanOperativo()) {
			if (!detallePlanOperativo.isEliminado()) {

				// Costo Tarea
				BigDecimal costoTarea = detallePlanOperativo.getCostoUnitario().multiply(detallePlanOperativo.getCantidad());
				detallePlanOperativo.setCostoTarea(costoTarea.setScale(2, RoundingMode.HALF_UP));

				int diasHabiles = obtenerDiasHabiles(detallePlanOperativo);

				if (diasHabiles > 0) {

					// Prorrateo
					BigDecimal cantidad = detallePlanOperativo.getCantidad();
					BigDecimal cantidadProporcional = cantidad.divide(new BigDecimal(obtenerDiasHabiles(detallePlanOperativo)), 2,
							RoundingMode.HALF_UP);
					TreeMap<Date, CronogramaPlanOperativo> tmCronogramaPlanOperativo = detallePlanOperativo.getTmCronogramaPlanOperativo();

					for (CronogramaPlanOperativo cronogramaPlanOperativo : tmCronogramaPlanOperativo.values()) {

						if (cronogramaPlanOperativo.getFecha().compareTo(tmCronogramaPlanOperativo.lastKey()) == 0) {
							cantidadProporcional = cantidad;
						}
						cronogramaPlanOperativo.setAvance(cantidadProporcional);
						cantidad = cantidad.subtract(cantidadProporcional);

					}

				}

			}
		}

		// Totaliza el peso de la tarea
		for (DetallePlanOperativo detallePlanOperativo : planOperativo.getListaDetallePlanOperativo()) {
			if (!detallePlanOperativo.isEliminado()) {
				if (planOperativo.getTotalCostoTarea().compareTo(BigDecimal.ZERO) != 0) {
					BigDecimal pesoTarea = (detallePlanOperativo.getCostoTarea().divide(planOperativo.getTotalCostoTarea(), 2, RoundingMode.HALF_UP))
							.multiply(new BigDecimal(100));
					detallePlanOperativo.setPeso(pesoTarea.setScale(2, RoundingMode.HALF_UP));
				}
			}
		}

	}

	/**
	 * VAlida el plan opertaivo antes de guardar
	 * 
	 * @return
	 */
	private boolean validar() {
		boolean resultado = true;
		for (DetallePlanOperativo detallePlanOperativo : planOperativo.getListaDetallePlanOperativo()) {
			if (!detallePlanOperativo.isEliminado()
					&& (detallePlanOperativo.getCantidad().compareTo(detallePlanOperativo.getTotalAvanceCronograma()) != 0)) {
				resultado = false;
				addInfoMessage("El avance del cronograma no coincide con el total planificado para el concepto :"
						+ detallePlanOperativo.getConcepto().getConcNombre());
			}
		}
		return resultado;
	}

	/**
	 * Obtener los dias habiles
	 * 
	 * @param detallePlanOperativo
	 */
	public int obtenerDiasHabiles(DetallePlanOperativo detallePlanOperativo) {

		int diasTarea = detallePlanOperativo.getDiasTarea() - 1;
		int diasHabiles = 0;

		if (diasTarea >= 0) {

			// Declaro e instancio las variables de las fechas de inicio y fin
			Calendar fechaInicial = Calendar.getInstance();
			fechaInicial.setTime(FuncionesUtiles.setAtributoFecha(detallePlanOperativo.getFechaInicio()));
			Calendar fechaFinal = Calendar.getInstance();

			fechaFinal.setTime(FuncionesUtiles.sumarFechaDiasMeses(fechaInicial.getTime(), diasTarea));
			// mientras la fecha inicial sea menor o igual que la fecha final se cuentan los dias
			while (fechaInicial.before(fechaFinal) || fechaInicial.equals(fechaFinal)) {

				// si el dia de la semana de la fecha minima es diferente de sabado o domingo
				if (fechaInicial.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY && fechaInicial.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY) {
					// se aumentan los dias de diferencia entre min y max
					diasHabiles++;
				} else {
					fechaFinal.add(Calendar.DATE, 1);
				}
				// se suma 1 dia para hacer la validacion del siguiente dia.
				fechaInicial.add(Calendar.DATE, 1);
			}
		}
		return diasHabiles;
	}

	/**
	 * Agrega una partida a la proforma
	 */
	public void agregarPartida() {
		partida = new ProdPartidaDetalle();
		partida.setProdCabeceraProforma(planOperativo.getProyecto().getProforma());
	}

	/**
	 * Guarda la partida creada
	 * 
	 */
	public void guardarPartida() {
		servicioDatosBaseProyectos.guardar(partida);
		listaPartidas = null;
	}

	/**
	 * Metodos Eventos
	 */

	/**
	 * Metodos GET Y SET
	 */

	public List<ProdConceptos> getListaConceptos() {
		if (listaConceptos == null) {
			listaConceptos = servicioDatosBaseProyectos.getObtenerConceptos();
		}
		return listaConceptos;
	}

	/**
	 * Get del atributo planOperativo
	 * 
	 * @return el valor del atributo planOperativo
	 */
	public PlanOperativo getPlanOperativo() {
		return planOperativo;
	}

	/**
	 * Set del atributo planOperativo
	 * 
	 * @param proyecto
	 *            valor para asignar al atributo planOperativo
	 */
	public void setPlanOperativo(PlanOperativo planOperativo) {
		this.planOperativo = planOperativo;
	}

	public Integer getIdProyecto() {
		return idProyecto;
	}

	public void setIdProyecto(Integer idProyecto) {
		this.idProyecto = idProyecto;
	}

	public DetallePlanOperativo getDetallePlanOperativoSeleccionado() {
		return detallePlanOperativoSeleccionado;
	}

	public void setDetallePlanOperativoSeleccionado(DetallePlanOperativo detallePlanOperativoSeleccionado) {
		this.detallePlanOperativoSeleccionado = detallePlanOperativoSeleccionado;
	}

	public LazyDataModel<PlanOperativo> getListaPlanOperativo() {
		return listaPlanOperativo;
	}

	public void setListaPlanOperativo(LazyDataModel<PlanOperativo> listaPlanOperativo) {
		this.listaPlanOperativo = listaPlanOperativo;
	}

	public DataTable getDtPlanOperativo() {
		return dtPlanOperativo;
	}

	public void setDtPlanOperativo(DataTable dtPlanOperativo) {
		this.dtPlanOperativo = dtPlanOperativo;
	}

	/**
	 * Get del atributo dtCronogramaPlanOperativo
	 * 
	 * @return el valor del atributo dtCronogramaPlanOperativo
	 */
	public DataTable getDtCronogramaPlanOperativo() {
		return dtCronogramaPlanOperativo;
	}

	/**
	 * Set del atributo dtCronogramaPlanOperativo
	 * 
	 * @param dtCronogramaPlanOperativo
	 *            valor para asignar al atributo dtCronogramaPlanOperativo
	 */
	public void setDtCronogramaPlanOperativo(DataTable dtCronogramaPlanOperativo) {
		this.dtCronogramaPlanOperativo = dtCronogramaPlanOperativo;
	}

	/**
	 * Get del atributo dtDetallePlanOperativo
	 * 
	 * @return el valor del atributo dtDetallePlanOperativo
	 */
	public DataTable getDtDetallePlanOperativo() {
		return dtDetallePlanOperativo;
	}

	/**
	 * Set del atributo dtDetallePlanOperativo
	 * 
	 * @param dtDetallePlanOperativo
	 *            valor para asignar al atributo dtDetallePlanOperativo
	 */
	public void setDtDetallePlanOperativo(DataTable dtDetallePlanOperativo) {
		this.dtDetallePlanOperativo = dtDetallePlanOperativo;
	}

	public HashMap<Date, Feriado> getHmFeriado() {
		if (hmFeriado == null) {
			hmFeriado = new HashMap<Date, Feriado>();
			for (Feriado feriado : servicioFeriado.obtenerListaCombo("", true, null)) {
				if (!hmFeriado.containsKey(feriado.getFecha())) {
					hmFeriado.put(feriado.getFecha(), feriado);
				}
			}
		}
		return hmFeriado;
	}

	public void setHmFeriado(HashMap<Date, Feriado> hmFeriado) {
		this.hmFeriado = hmFeriado;
	}

	/**
	 * Get del atributo listaPartidas
	 * 
	 * @return el valor del atributo listaPartidas
	 */
	public List<ProdPartidaDetalle> getListaPartidas() {
		if (listaPartidas == null) {
			listaPartidas = servicioDatosBaseProyectos.getObtenerPartidas(planOperativo.getProyecto().getProforma());
		}
		return listaPartidas;
	}

	public ProdPartidaDetalle getPartida() {
		return partida;
	}

	public void setPartida(ProdPartidaDetalle partida) {
		this.partida = partida;
	}

	public StreamedContent getChartImage() {
		return chartImage;
	}

	public void setChartImage(StreamedContent chartImage) {
		this.chartImage = chartImage;
	}

	public void actualizarCronograma() {

		String image = planOperativo.getImagen() != null ? planOperativo.getImagen() : planOperativo.getProyecto().getNumero() + "-"
				+ planOperativo.getVersion() + ".png";
		planOperativo.setImagen(image);

		try {

			TaskSeries taskSeries = new TaskSeries("Avance");
			for (DetallePlanOperativo detallePlanOperativo : planOperativo.getListaDetallePlanOperativo()) {
				if (!detallePlanOperativo.isEliminado()) {
					taskSeries.add(new Task(detallePlanOperativo.getConcepto().getConcNombre(), new SimpleTimePeriod(detallePlanOperativo
							.getFechaInicio(), detallePlanOperativo.getFechaFin())));
				}
			}

			TaskSeriesCollection collection = new TaskSeriesCollection();
			collection.add(taskSeries);

			JFreeChart jfreechart = ChartFactory.createGanttChart("Cronograma", "Tareas", "Dias", collection, true, true, false);
			File chartFile = new File("D:" + File.separator + image);
			if (chartFile.exists()) {
				chartFile.delete();
			}
			ChartUtilities.saveChartAsPNG(chartFile, jfreechart, 1400, 400);
			chartImage = new DefaultStreamedContent(new FileInputStream(chartFile), "image/png");

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}
